package com.jprocms.module.cms.controller.admin.channel;

import cn.hutool.core.collection.CollUtil;
import com.jpro.framework.common.pojo.CommonResult;
import com.jpro.framework.common.util.collection.CollectionUtils;
import com.jpro.framework.datapermission.core.annotation.DataPermission;
import com.jpro.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
import com.jpro.framework.security.core.util.SecurityFrameworkUtils;
import com.jprocms.module.cms.controller.admin.channel.dto.ChannelRuleDto;
import com.jprocms.module.cms.controller.admin.channel.vo.*;
import com.jprocms.module.cms.convert.channel.ChannelConvert;
import com.jprocms.module.cms.dal.dataobject.channel.ChannelDO;
import com.jprocms.module.cms.dal.dataobject.channel.ChannelExtDO;
import com.jprocms.module.cms.dal.dataobject.model.ModelDO;
import com.jprocms.module.cms.dal.dataobject.site.SiteDO;
import com.jprocms.module.cms.dal.mysql.channel.ChannelExtMapper;
import com.jprocms.module.cms.dal.mysql.model.ModelMapper;
import com.jprocms.module.cms.enums.EnumChannelFilterType;
import com.jprocms.module.cms.enums.EnumRecycle;
import com.jprocms.module.cms.permission.ContentPermissionRule;
import com.jprocms.module.cms.service.channel.ChannelAttrService;
import com.jprocms.module.cms.service.channel.ChannelExtService;
import com.jprocms.module.cms.service.channel.ChannelService;
import com.jprocms.module.cms.service.staticpage.StaticHtmlProducer;
import com.jprocms.module.cms.service.staticpage.StaticHtmlService;
import com.jprocms.module.cms.util.CmsContextUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.jpro.framework.common.pojo.CommonResult.success;
import static com.jprocms.module.cms.dal.dataobject.task.TaskDO.TASK_NAME_CHANNEL_AUTO;

@Tag(name = "管理后台 - 栏目")
@RestController
@RequestMapping("/cms/channel")
@Validated
@DataPermission(excludeRules = {DeptDataPermissionRule.class, ContentPermissionRule.class})
public class ChannelController {

    @Resource
    private ChannelService channelService;
    @Resource
    private ChannelExtService channelExtService;
    @Resource
    private ChannelAttrService channelAttrService;

    @Resource
    private ModelMapper modelMapper;
    @Resource
    private ChannelExtMapper channelExtMapper;
    @Resource
    private StaticHtmlProducer staticHtmlProducer;
    @Resource
    private StaticHtmlService staticHtmlService;

    @PostMapping("/create")
    @Operation(summary = "创建栏目")
    @PreAuthorize("@ss.hasPermission('cms:channel:create')")
    public CommonResult<Long> createChannel(@Valid @RequestBody ChannelCreateReqVO createReqVO) {
        final Long channelId = channelService.createChannel(createReqVO);
        //生成静态页
        ChannelDO channel = channelService.getChannel(channelId);
        if (channel.getSite().getEnabledAndAuto()) {
            staticHtmlProducer.updateChannelRelatedHtml(channel.getSiteId(), SecurityFrameworkUtils.getLoginUserId(), TASK_NAME_CHANNEL_AUTO, channel.getId());
        }
        return success(channelId);
    }

    @PutMapping("/update")
    @Operation(summary = "更新栏目")
    @PreAuthorize("@ss.hasPermission('cms:channel:update')")
    public CommonResult<Boolean> updateChannel(@Valid @RequestBody ChannelUpdateReqVO updateReqVO) {
        channelService.updateChannel(updateReqVO);
        ChannelDO channel = channelService.getChannel(updateReqVO.getId());
        //生成静态页
        if (channel.getSite().getEnabledAndAuto()) {
            staticHtmlProducer.updateChannelRelatedHtml(channel.getSiteId(), SecurityFrameworkUtils.getLoginUserId(), TASK_NAME_CHANNEL_AUTO, channel.getId());
        }
        return success(true);
    }

    @PostMapping("/updateChannelRule")
    @Operation(summary = "更新栏目")
    @PreAuthorize("@ss.hasPermission('cms:channel:update')")
    public CommonResult<Boolean> updateChannelRule(@Valid @RequestBody ChannelRuleDto ruleDto) {
        channelService.updateChannelRule(ruleDto);
        return success(true);
    }

    @GetMapping("/getChannelRule")
    @Operation(summary = "获得栏目规则配置")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<ChannelRuleDto> getChannelRule(@RequestParam("id") Long id) {
        ChannelExtDO channelExt = channelExtService.getChannelExt(id);
        ChannelRuleDto rule = channelExt.getCollectRule();
        return success(rule);
    }

    @PostMapping("/recycle")
    @Operation(summary = "删除栏目到回收站")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('cms:channel:delete')")
    public CommonResult<Boolean> recycleChannel(@RequestParam("id") Long id) throws Exception {
        channelService.recycleChannel(id);
        //删除静态页
        final ChannelDO channel = channelService.getChannel(id);
        //先删除静态页
        staticHtmlService.deleteChannelHtml(channel);
        SiteDO site = channel.getSite();
        final Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (site.getEnabledAndAuto()) {
            staticHtmlProducer.updateChannelRelatedHtml(channel.getSiteId(), userId, TASK_NAME_CHANNEL_AUTO, channel.getId());
        }
        return success(true);
    }

    @PostMapping("/delete")
    @Operation(summary = "彻底删除栏目")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('cms:channel:delete')")
    public CommonResult<Boolean> deleteChannel(@RequestParam("id") Long id) throws Exception {
        final ChannelDO channel = channelService.getChannel(id);
        channelService.deleteChannel(id);
        return success(true);
    }

    @PostMapping("/restore")
    @Operation(summary = "还原栏目")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('cms:channel:delete')")
    public CommonResult<Boolean> restoreChannel(@RequestParam("id") Long id) {
        channelService.restoreChannel(id);
        final ChannelDO channel = channelService.getChannel(id);
        //重新生成静态页
        SiteDO site = channel.getSite();
        final Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (site.getEnabledAndAuto()) {
            staticHtmlProducer.updateChannelRelatedHtml(channel.getSiteId(), userId, TASK_NAME_CHANNEL_AUTO, channel.getId());
        }
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得栏目")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<ChannelRespVO> getChannel(@RequestParam("id") Long id) {
        ChannelDO channel = channelService.getChannel(id);
        return success(ChannelConvert.INSTANCE.convertToResp(channel, channel.getChannelExt(), channel.getChannelModel(), channel.getAttrDos()));
    }

    @GetMapping("/list")
    @Operation(summary = "获得栏目列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<List<ChannelListRespVO>> getChannelList(@RequestParam("ids") Collection<Long> ids) {
        List<ChannelDO> list = channelService.getChannelList(ids);
        List<ModelDO> modelDOS = modelMapper.selectBatchIds(CollectionUtils.convertList(list, ChannelDO::getModelId));
        Map<Long, String> modelIdNameMap = CollectionUtils.convertMap(modelDOS, ModelDO::getId, ModelDO::getName);
        return success(ChannelConvert.INSTANCE.convertListResp(list, modelIdNameMap));
    }

    @GetMapping("/tree")
    @Operation(summary = "获得栏目管理树")
    @Parameter(name = "name", description = "名称")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<List<ChannelListRespVO>> getChannelTree(@RequestParam(value = "name", required = false) String name,
                                                                @RequestParam(value = "siteId", required = false) Long siteId) {
        ChannelListReqVO reqVO = new ChannelListReqVO();
        reqVO.setRecycleStatus(EnumRecycle.NO_RECYCLE.getStatus());
        reqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        if (siteId != null) {
            reqVO.setSiteId(siteId);
        }
//        reqVO.setName(name);
        reqVO.setKey(name);
        List<ChannelListRespVO> channelsTreeVos = channelService.getChannelsTreeVo(reqVO);
        //如果搜索条件不为空则name属性调整栏目面包屑数据 方面前端处理展示搜索到多层相同名称处理
        if (StringUtils.isNotBlank(name) && !channelsTreeVos.isEmpty()) {
            for (ChannelListRespVO channelsTreeVo : channelsTreeVos) {
                channelsTreeVo.setName(CollUtil.join(channelsTreeVo.getNodeNames(), "/"));
            }
        }
        return success(channelsTreeVos);
    }

    @GetMapping("/getRecycleTree")
    @Operation(summary = "获得栏目管理树")
    @Parameter(name = "name", description = "名称")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<List<ChannelListRespVO>> getRecycleTree(@RequestParam(value = "name", required = false) String name,
                                                                @RequestParam(value = "siteId", required = false) Long siteId) {
        ChannelListReqVO reqVO = new ChannelListReqVO();
        reqVO.setRecycleStatus(EnumRecycle.RECYCLE.getStatus());
        reqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        if (siteId != null) {
            reqVO.setSiteId(siteId);
        }
        reqVO.setKey(name);
        List<ChannelListRespVO> channelsTreeVos = channelService.getChannelsTreeVo(reqVO);
        //如果搜索条件不为空则name属性调整栏目面包屑数据 方面前端处理展示搜索到多层相同名称处理
        if (StringUtils.isNotBlank(name) && !channelsTreeVos.isEmpty()) {
            for (ChannelListRespVO channelsTreeVo : channelsTreeVos) {
                channelsTreeVo.setName(CollUtil.join(channelsTreeVo.getNodeNames(), "/"));
            }
        }
        return success(channelsTreeVos);
    }

    @GetMapping("/list-all-simple")
    @Operation(summary = "获取栏目精简信息列表")
    public CommonResult<List<ChannelSimpleRespVO>> getSimpleChannelList(@RequestParam(value = "siteId", required = false) Long siteId) {
        ChannelSimpleReqVO reqVO = new ChannelSimpleReqVO();
        reqVO.setRecycleStatus(EnumRecycle.NO_RECYCLE.getStatus());
        if (siteId != null) {
            reqVO.setSiteId(siteId);
        } else {
            reqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        }
        List<ChannelDO> list = channelService.getChannelOptions(reqVO);
        // 排序后，返回给前端
        list.sort(Comparator.comparing(ChannelDO::getSort));
        return success(ChannelConvert.INSTANCE.convertSimpleList(list));
    }

    @GetMapping("/getContentChannelTree")
    @Operation(summary = "获得内容的栏目管理树")
    @Parameter(name = "name", description = "名称")
    @PreAuthorize("@ss.hasPermission('cms:content:query')")
    public CommonResult<List<ChannelListRespVO>> getContentChannelTree(@RequestParam(value = "name", required = false) String name,
                                                                       @RequestParam(value = "siteId", required = false) Long siteId) {
        ContentChannelListReqVO reqVO = new ContentChannelListReqVO();
        reqVO.setRecycleStatus(EnumRecycle.NO_RECYCLE.getStatus());
        reqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        if (siteId != null) {
            reqVO.setSiteId(siteId);
        }
        reqVO.setKey(name);
        List<ChannelListRespVO> channelsTreeVos = channelService.getContentChannelsTreeVo(reqVO);
        //如果搜索条件不为空则name属性调整栏目面包屑数据 方面前端处理展示搜索到多层相同名称处理
        if (StringUtils.isNotBlank(name) && !channelsTreeVos.isEmpty()) {
            for (ChannelListRespVO channelsTreeVo : channelsTreeVos) {
                channelsTreeVo.setName(CollUtil.join(channelsTreeVo.getNodeNames(), "/"));
            }
        }
        return success(channelsTreeVos);
    }

    /**
     * 获得栏目访问量统计列表
     *
     * @param filterType 过滤栏目类型  1 所有栏目 2 顶层栏目  3 底层栏目 默认 2顶层
     * @param siteId     站点ID 默认当前访问站点
     * @return
     */
    @GetMapping("/getChannelView")
    @Operation(summary = "获得栏目访问量统计列表")
    @Parameter(name = "name", description = "名称")
    @PreAuthorize("@ss.hasPermission('cms:channel:query')")
    public CommonResult<List<ChannelViewListRespVO>> getChannelViewList(@RequestParam(value = "filterType", required = false) Integer filterType,
                                                                        @RequestParam(value = "siteId", required = false) Long siteId) {
        ChannelListReqVO reqVO = new ChannelListReqVO();
        reqVO.setRecycleStatus(EnumRecycle.NO_RECYCLE.getStatus());
        reqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        if (siteId != null) {
            reqVO.setSiteId(siteId);
        }
        if (filterType == null) {
            filterType = EnumChannelFilterType.TOP_CHANNEL.getType();
        }
        List<ChannelViewListRespVO> channelsVos = channelService.getChannelsViewListVo(reqVO);
        if (CollUtil.isEmpty(channelsVos)) {
            return success(channelsVos);
        }
        final List<Long> parentIds = CollectionUtils.convertList(channelsVos, ChannelViewListRespVO::getParentId);
        if (EnumChannelFilterType.TOP_CHANNEL.getType().equals(filterType)) {
            channelsVos = channelsVos.stream().filter(c -> c.getParentId() == null).collect(Collectors.toList());
        } else if (EnumChannelFilterType.BUTTOM_CHANNEL.getType().equals(filterType)) {
            channelsVos = channelsVos.stream().filter(c -> !parentIds.contains(c.getId())).collect(Collectors.toList());
        }
        //非底层栏目 方面前端处理展示搜索到多层相同名称处理
        if (!EnumChannelFilterType.BUTTOM_CHANNEL.getType().equals(filterType) && !channelsVos.isEmpty()) {
            for (ChannelViewListRespVO channelsTreeVo : channelsVos) {
                channelsTreeVo.setName(CollUtil.join(channelsTreeVo.getNodeNames(), "/"));
            }
        }
        return success(channelsVos);
    }

    @PostMapping("/batchCreate")
    @Operation(summary = "批量创建栏目")
    @PreAuthorize("@ss.hasPermission('cms:channel:create')")
    public CommonResult<List<Long>> batchCreateChannel(@Valid @RequestBody ChannelBatchCreateVO batchCreateReqVO) {
        final List<Long> channelIds = channelService.batchCreateChannel(batchCreateReqVO);
        //生成静态页
        for (Long channelId : channelIds) {
            ChannelDO channel = channelService.getChannel(channelId);
            if (channel.getSite().getEnabledAndAuto()) {
                staticHtmlProducer.updateChannelRelatedHtml(channel.getSiteId(), SecurityFrameworkUtils.getLoginUserId(), TASK_NAME_CHANNEL_AUTO, channel.getId());
            }
        }
        return success(channelIds);
    }


}
